package com.liu.yubi.algorithm;


import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

/**
 * @author lqh
 * @since 2025-05-31 23:46
 * 滑动窗口限流算法
 */
public class SlidAlgorithm {

    /**
     * 窗口期(窗口时间)
     */
    private final Long windowTime;

    /**
     * 阀值（窗口时间内限制请求）
     */
    private final Integer requestMax;

    /**
     * 计数器（可进可出：滑动效果）
     */
    private final LinkedList<Long> requests;

    public SlidAlgorithm(Long windowTime, Integer requestMax) {
        this.windowTime = windowTime;
        this.requestMax = requestMax;
        requests=new LinkedList<>();
    }

    public boolean tryAcquire(){
        //当前时间
        long now = System.currentTimeMillis ();
        //移除窗口外的计数(移除固定窗口期之外的请求技术)
        while (!requests.isEmpty () && (now-requests.peekFirst ())>windowTime){
            //移除请求(最开始的请求)
            requests.pollFirst ();
        }
        //判断阈值
        if (requests.size ()<requestMax){
            //计数器+1
            requests.add (now);
            //通过
            return true;
        }
        //拒绝
        return false;

    }
    /**
     * 测试
     */
    public static void main(String[] args) throws Exception  {
        //窗口期1s 最大请求数2
        SlidAlgorithm slidAlgorithm=new SlidAlgorithm (1000L,2);
        for (int i = 0; i < 5; i++) {
            System.out.println (slidAlgorithm.tryAcquire ()? "通过":"拒绝");
            Thread.sleep (200L);
        }
                // 等待窗口过期
        TimeUnit.MILLISECONDS.sleep(500);
        System.out.println("尝试请求 4: " +
                (slidAlgorithm.tryAcquire() ? "通过" : "拒绝"));
    }

}
